using System.Reflection;
using System.Text;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using BlogSystem.Common.Config;
using BlogSystem.Common.Config.DI;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddControllers();

#region AutoFac
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<Autofac.ContainerBuilder>(containerBuilder =>
{
    containerBuilder.RegisterModule<AutofacRegisterModule>();

// 瞬时注入【默认】：containerBuilder.RegisterType<UserServiceImpl>().As<IUserService>().InstancePerDependency();
//
// 单例注入：containerBuilder.RegisterType<UserService>().As<IUserService>().SingleInstance();
//
// 生命周期注入： containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();

});
#endregion

#region mediator

//builder.Services.AddMediatR(typeof(INotificationHandler<TNotification>).GetTypeInfo().Assembly);

#endregion


#region 数据库配置
builder.Services.AddScoped<DbContext, DataBaseContext>();
builder.Services.AddDbContext<DataBaseContext>(opt => {
    string connectionString = builder.Configuration.GetConnectionString("MySQLConnection");
    var serverVersion = ServerVersion.AutoDetect(connectionString);
    opt.UseMySql(connectionString, new MySqlServerVersion("8.0"));
});
#endregion


#region Swagger集成JWt

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1",new OpenApiInfo{Title = "jwtswagger",Version = "v1"});
    // var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    // var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    //c.IncludeXmlComments(xmlPath);
    c.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
    {
        Description = "格式：Bearer token",
        Name = "Authorization", // 默认的参数名
        In = ParameterLocation.Header, // 放于请求头中
        Type = SecuritySchemeType.ApiKey,
        BearerFormat = "JWT",
        Scheme = "Bearer"
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            new string[] { }
        }
    });
});
#endregion


#region JWT服务
// 注册JWT服务
//builder.Services.AddSingleton(new JWTHelper(builder.Configuration));
 
builder.Services.AddAuthentication(options =>
    { //身份验证服务
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    }
).AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateIssuer = true, //是否验证Issuer
            ValidIssuer = builder.Configuration["Jwt:Issuer"], //发行人Issuer
            ValidateAudience = true, //是否验证Audience
            ValidAudience = builder.Configuration["Jwt:Audience"], //订阅人Audience
            ValidateIssuerSigningKey = true, //是否验证SecurityKey
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"])), //SecurityKey
            ValidateLifetime = true, //是否验证失效时间
            ClockSkew = TimeSpan.FromHours(5), //过期时间容错值，解决服务器端时间不同步问题（秒）
            RequireExpirationTime = true,
        };
    }
);
#endregion

#region FluentValidation校验配置

builder.Services.AddControllers()
    
    .AddFluentValidation(fv => fv.RegisterValidatorsFromAssembly(Assembly.GetExecutingAssembly()));

//单独
// builder.Services.AddTransient<IValidator<LoginRequets>,LoginValidatior>();
// builder.Services.AddTransient<IValidator<RegisterRequest>, RegisterValidatior>();

#endregion

#region 注入AutoMapper服务

builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

//单独注册
// builder.Services.AddAutoMapper(typeof(UserProfile));
// builder.Services.AddAutoMapper(typeof(ArticleProifle));
#endregion


#region 全局访问

//builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddHttpContextAccessor();

#endregion

#region Serilog使用
// Log.Logger = new LoggerConfiguration() //创建一个日志记录配置器
//     .MinimumLevel.Information() //设置最低记录级别
//     .Enrich.FromLogContext() //允许启动日志上下文
//     .WriteTo.Console() //输出到控制台
//     .CreateLogger(); //创建日志记录器
// builder.Logging.AddSerilog(Log.Logger);//将Serilog作为日志记录器
// builder.Host.UseSerilog((context, services, configuration) =>
// {
//     // 从配置文件中读取配置
//     configuration.ReadFrom.Configuration(context.Configuration);
// });

// 定义一个日志输出模板  时间戳 线程iD 
// const string OUTPUT_TEMPLATE = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} <{ThreadId}> [{Level:u3}] {Message:lj}{NewLine}{Exception}";
// Log.Logger = new LoggerConfiguration()
//     .MinimumLevel.Debug() //最低级别的debug
//     .Enrich.WithThreadId() // 丰富日志条目  添加线程id
//     .Enrich.FromLogContext() // 从日志上下文 中丰富日志条目
//     .WriteTo.Console(outputTemplate: OUTPUT_TEMPLATE)  // 将日志写入控制台 使用上面定义的模板
//     .WriteTo.File("logs/app.txt" //将日志写入文件 
//         , rollingInterval: RollingInterval.Day //每天滚动一次文件
//         , outputTemplate: OUTPUT_TEMPLATE) 
//     .CreateLogger();//创建并返回 配置好的日志记录器
//
// Log.Information("Starting web host"); // 记录一条信息级别的日志  表示webHost正在启动
//     
// builder.Host.UseSerilog(Log.Logger, dispose: true); //使用Serilog日志记录器 集成到webHost当中

#endregion

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.MapControllers();
app.UseHttpsRedirection();

//启动身份验证中间件
app.UseAuthentication();
app.UseAuthorization();


app.Run();
//Log.CloseAndFlush();

